package git.bds.nyc.framework.web.config;

import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.jwt.StpLogicJwtForSimple;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import javax.servlet.Filter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author 成大事
 * @since 2022/5/24 16:14
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {


    /**
     * 解决swagger映射
     * @param registry    ResourceHandlerRegistry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");

        /* 配置knife4j 显示文档 */
        registry.addResourceHandler("doc.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        /*
         * 配置swagger-ui显示文档
         */
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        /* 公共部分内容 */
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }


    /**
     * 解决乱码
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        for (HttpMessageConverter<?> converter : converters) {
            // 解决 Controller 返回普通文本中文乱码问题
            if (converter instanceof StringHttpMessageConverter) {
                ((StringHttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8);
            }

            // 解决 Controller 返回json对象中文乱码问题
            if (converter instanceof MappingJackson2HttpMessageConverter) {
                ((MappingJackson2HttpMessageConverter) converter).setDefaultCharset(StandardCharsets.UTF_8);
            }
        }
    }

    /**
     * 创建 CorsFilter Bean，解决跨域问题
     */
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilterBean() {
        // 创建 CorsConfiguration 对象
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        // 设置访问源地址
        config.addAllowedOriginPattern("*");
        // 设置访问源请求头
        config.addAllowedHeader("*");
        // 设置访问源请求方法
        config.addAllowedMethod("*");
        // 创建 UrlBasedCorsConfigurationSource 对象
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        // 对接口配置跨域设置
        source.registerCorsConfiguration("/**", config);
        return createFilterBean(new CorsFilter(source));
    }

    /**
     * 创建筛选器bean
     *
     * @param filter 滤器
     * @return {@link FilterRegistrationBean}<{@link T}>
     */
    private static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter) {
        FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
        bean.setOrder(Integer.MAX_VALUE);
        return bean;
    }



    /**
     * mybatis-plus 枚举类返回
     *
     * @return {@link Jackson2ObjectMapperBuilderCustomizer}
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer customizer(){
        return builder -> builder.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
    }



    /**Sa-Token 整合 jwt (Simple 简单模式)*/
    @Bean
    public StpLogic getStpLogicJwt() {
        return new StpLogicJwtForSimple();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        List<String> urls = new ArrayList<>();
        //释放swagger 映射
        urls.add("/favicon.ico");
        urls.add("/error");
        urls.add("/swagger-resources/**");
        urls.add("/webjars/**");
        urls.add("/v2/**");
        urls.add("/doc.html");
        urls.add("**/swagger-ui.html");
        urls.add("/swagger-ui.html/**");

        // 注册 Sa-Token 拦截器，定义详细认证规则
        registry.addInterceptor(new SaInterceptor(handler -> {
            // //登录认证 -- 拦截所有路由，并排除/user/doLogin 用于开放登录
            SaRouter.match("/**")
                    .notMatch("/applet/user/login")
                    .notMatch("/applet/user/loginTest")
                    .notMatch("/applet/index/advertisement/**")
                    .notMatch("/applet/index/**")
                    .notMatch("/applet/index/details/**")
                    .notMatch("/admin/loginByPassword")
                    .notMatch("/coop/loginByPassword")
                    .notMatch("/applet/demand/getDemandPageByEs")
                    .notMatch("/applet/index/search/**")
                    .notMatch(urls)
                    .check(r-> StpUtil.checkLogin());

            // 根据路由划分模块，不同模块不同鉴权
            // 角色认证 -- 拦截以 admin 开头的路由，必须具备 admin 角色或者 super-admin 角色才可以通过认证
            SaRouter.match("/applet/mine/release-manage/**", r -> StpUtil.checkRoleOr("corp", "farmer"));
            SaRouter.match("/applet/mine/address/**", r -> StpUtil.checkRoleOr("corp", "farmer"));
            SaRouter.match("/applet/mine/collection/**", r -> StpUtil.checkRoleOr("corp", "farmer","visitor"));
            SaRouter.match("/applet/mine/history/**", r -> StpUtil.checkRoleOr("corp", "farmer","visitor"));
            SaRouter.match("/applet/mine/order-handler/**", r -> StpUtil.checkRoleOr("corp", "farmer"));
            SaRouter.match("/applet/mine/demand-handler/**", r -> StpUtil.checkRoleOr("corp", "farmer"));
            SaRouter.match("/applet/order/**", r -> StpUtil.checkRoleOr("corp", "farmer","visitor"));
            SaRouter.match("/applet/index/release/**", r -> StpUtil.checkRoleOr("corp", "farmer"));
            SaRouter.match("/coop/audit/**", r -> StpUtil.checkRoleOr("coop"));
            SaRouter.match("/common/audit/**", r -> StpUtil.checkRoleOr("coop","admin"));
            SaRouter.match("/admin/role-permission/**", r -> StpUtil.checkRoleOr("admin"));
            SaRouter.match("/admin/user/**", r -> StpUtil.checkRoleOr("admin"));
            SaRouter.match("/admin/coop/**", r -> StpUtil.checkRoleOr("admin"));
            SaRouter.match("/admin/advertisement/**", r -> StpUtil.checkRoleOr("admin"));
            SaRouter.match("/admin/order/**", r -> StpUtil.checkRoleOr("admin"));
            SaRouter.match("/admin/agreement/**", r -> StpUtil.checkRoleOr("admin"));
            SaRouter.match("/admin/audit/**", r -> StpUtil.checkRoleOr("admin"));


            //上传文件的
            SaRouter.match("/applet/file/uploadProductImg", r -> StpUtil.checkRoleOr("corp", "farmer"));
            SaRouter.match("/applet/file/uploadDemandImg", r -> StpUtil.checkRoleOr("corp", "farmer"));
            SaRouter.match("/applet/file/uploadAvatar", r -> StpUtil.checkRoleOr("corp", "farmer","visitor"));
            SaRouter.match("/applet/file/uploadIdCardFrontImg", r -> StpUtil.checkRoleOr("corp", "farmer","visitor"));
            SaRouter.match("/applet/file/uploadIdCardBackImg", r -> StpUtil.checkRoleOr("corp", "farmer","visitor"));
            SaRouter.match("/applet/file/uploadEnterpriseLicenseImg", r -> StpUtil.checkRoleOr("corp", "farmer","visitor"));
        })).addPathPatterns("/**");
    }

}
